#include "rrprim.h"
#include "rrmath.h"
#include <cmath>
#include <cstdio>

RRPrim::RRPrim(){ }

void RRPrim::rrSetYPlane(float y)
{
    t = RR_PLANE;
    Yplane = y;
}


void RRPrim::rrSetSphere(float xc, float yc, float zc, float r)
{
    t = RR_SPHERE;
    Pc = RRSetVec3(xc, yc, zc);
    Rad = r;
}

float RRPrim::rrGetDistance(RREye arg)
{
    e = arg;
    RRVec3 e_coord, e_dir, temp;
    e_coord = e.rrGetEyeCoord();
    e_dir = e.rrGetEyeDir();
    if(t == RR_SPHERE) {
        float A, B, C;
        A = RRInnerProduct(e_dir, e_dir);
        temp = RRSetVec3(e_coord.x - Pc.x, e_coord.y - Pc.y, e_coord.z - Pc.z);
        B = RRInnerProduct(e_dir, temp);
        C = RRInnerProduct(temp, temp) - Rad * Rad;
        D = B * B - A * C;
        if(D > 0) {
            Coefficient = (-B - sqrtf(D)) / A;
            P = RRSetVec3(e_coord.x + e_dir.x * Coefficient, e_coord.y + e_dir.y * Coefficient, e_coord.z + e_dir.z * Coefficient);
            temp = RRSetVec3(e_dir.x * Coefficient, e_dir.y * Coefficient, e_dir.z * Coefficient);
            return sqrtf(temp.x * temp.x + temp.y * temp.y + temp.z * temp.z);
        }
        else
            return -1.0f;
    }
    else if(t == RR_PLANE) {
        Coefficient = 100.0f;
        float B, C;
        B = e_coord.y + e_dir.y * Coefficient;
        if(B > Yplane) {
            float y_co;
            y_co = (Yplane - e_coord.y) / e_dir.y;
            P = RRSetVec3(e_coord.x + e_dir.x * y_co, Yplane, e_coord.z + e_dir.z * y_co);
            temp = RRSetVec3(e_dir.x * y_co, e_dir.y * y_co, e_dir.z * y_co);
            return sqrtf(temp.x * temp.x + temp.y * temp.y + temp.z * temp.z);
        }
        else
            return -1.0f;
    }
    else
        return -1.0f;
}

RRVec3 RRPrim::rrGetColor(RRLight arg)
{
    l = arg;
    //光源位置
    RRVec3 l_coord;
    l_coord = l.rrGetLightCoord();
    //視線
    RRVec3 e_coord, e_dir;
    e_coord = e.rrGetEyeCoord();
    e_dir = e.rrGetEyeDir();
    float A, B;
    if(t == RR_SPHERE) {
        //法線ベクトル
        RRVec3 N;
        N = RRSetVec3(P.x - Pc.x, P.y - Pc.y, P.z - Pc.z);
        N = RRNormalize(N);
        //光源へのベクトル
        RRVec3 L;
        L = RRSetVec3(l_coord.x - P.x, l_coord.y - P.y, l_coord.z - P.z);
        L = RRNormalize(L);
        //拡散反射強度
        A = RRInnerProduct(N, L);
        //光源からの反射ベクトル
        RRVec3 R;
        R = RRSetVec3(2 * A * N.x - L.x, 2 * A * N.y - L.y, 2 * A * N.z - L.z);
        R = RRNormalize(R);
        //視線方向へのベクトル
        RRVec3 V;
        V = RRSetVec3(-e_dir.x * Coefficient, -e_dir.y * Coefficient, -e_dir.z * Coefficient);
        V = RRNormalize(V);
        //鏡面反射強度
        B = RRInnerProduct(R, V);
        if(B < 0) B = 0.0f;
        B = powf(B, 10.0f);

        if(A < 0) A = 0.0f;
        //printf("%f %f\n", A, B);

        RRVec3 Ret;
        Ret = RRSetVec3(B, B, B + A * 0.8f);
        RRClampVec3(&Ret, 0.0f, 1.0f);
        return Ret;
    }
    else if(t == RR_PLANE) {
        RRVec3 N, L;
        N = RRSetVec3(0.0f, -1.0f, 0.0f);
        L = RRSetVec3(l_coord.x - P.x, l_coord.y - P.y, l_coord.z - P.z);
        L = RRNormalize(L);
        A = RRInnerProduct(N, L);
        if(A < 0) A = 0.0f;
        RRVec3 Ret;
        Ret = RRSetVec3(A, 0.0f, 0.0f);
        return Ret;
    }
    else
        return RRSetVec3(0.0f, 0.0f, 0.0f);
}
